#include "stream_reassembler.hh"

// Dummy implementation of a stream reassembler.

// For Lab 1, please replace with a real implementation that passes the
// automated checks run by `make check_lab1`.

// You will need to add private members to the class declaration in `stream_reassembler.hh`

using namespace std;

StreamReassembler::StreamReassembler(const size_t capacity) : _output(capacity), _capacity(capacity) {}

//! \details This function accepts a substring (aka a segment) of bytes,
//! possibly out-of-order, from the logical stream, and assembles any newly
//! contiguous substrings and writes them into the output stream in order.
void StreamReassembler::push_substring(const string &data, const size_t index, const bool eof) {
    size_t first_index = index;
    size_t last_index = index + data.size() - 1;
    // 最后一个字符的位置
    if (last_index > _first_index + _capacity - 1)
        last_index = _first_index + _capacity - 1;
    if (first_index < _first_index)
        first_index = _first_index;
    
    // 查找左边的第一个区间
    size_t l = first_index, r = last_index;
    
    if (l <= r && data.size() > 0) {
        string s = string().assign(data, first_index - index, last_index - first_index + 1);
        vector<node> v;
        auto it = _interval.lower_bound(node{first_index, 0});
        string l_string = "", r_string = "";
        if (it != _interval.begin()) {
            --it;
            if (it->r + 1 >= l) {
                v.push_back(*it);
                l_string.assign(it->data, 0, l - it->l);
                l = min(l, it->l);
                _unassembled_bytes -= (it->r - it->l + 1);
            }
            if (r <= it->r)
                r_string.assign(it->data, r + 1 - it->l);
            r = max(r, it->r);
            ++it;
        } 
        while (it != _interval.end() && r >= it->l - 1) {
            v.push_back(*it);
            if (r <= it->r)
                r_string.assign(it->data, r + 1 - it->l);
            _unassembled_bytes -= (it->r - it->l + 1);
            r = max(r, it->r);
            ++it;
        }
        for (auto e:v)
            _interval.erase(_interval.find(e));
        _interval.insert(node{l, r, l_string + s + r_string});
        _unassembled_bytes += r - l + 1;
    
        auto first_interval = _interval.begin();
    //    cerr << "---" << first_interval->l << " " << first_interval->r << " " << _unassembled_bytes << " " << _first_index  << endl;
        if (first_interval->l == _first_index) {
            size_t sz = min(first_interval->data.size(), _output.remaining_capacity());
            _output.write(first_interval->data.substr(0, sz));
            _interval.erase(first_interval);
            _unassembled_bytes -= sz;
            _first_index += sz;
        }
    }
    if (eof) 
        _eof = true;
    // 网络层停止push,并且所有字节已经重组完成,终止输入
    if (_eof && empty())
        _output.end_input();
}

size_t StreamReassembler::unassembled_bytes() const { 
    return _unassembled_bytes;
}

bool StreamReassembler::empty() const { 
    return _unassembled_bytes == 0;
}

size_t StreamReassembler::get_first_bytes() const {
    return _first_index;
}
